// © 2004 Olivier Galizzi <olivier.galizzi@imag.fr>
// © 2006 Janek Kozicki <cosurgi@berlios.de>
#pragma once

#ifdef WOO_OPENGL

#include<woo/lib/multimethods/FunctorWrapper.hpp>
#include<woo/core/Dispatcher.hpp>
#include<woo/lib/pyutil/converters.hpp>
#include<woo/core/Master.hpp>


#define RENDERS(name) public: virtual string renders() const WOO_CXX11_OVERRIDE { return #name;}; FUNCTOR1D(name);

struct scene;
struct Renderer;

struct GLViewInfo{
	GLViewInfo(): sceneCenter(Vector3r::Zero()), sceneRadius(1.){}
	Vector3r sceneCenter;
	Real sceneRadius;
	Scene* scene;
	Renderer* renderer;
};


#define GL_FUNCTOR(Klass,typelist,renderedType) class Klass: public Functor1D<renderedType,void,typelist>{public:\
	virtual string renders() const { throw std::runtime_error(#Klass ": unregistered gldraw class.\n"); };\
	virtual void initgl(){/*WARNING: it must deal with static members, because it is called from another instance!*/};\
	/* API check only */ void pyHandleCustomCtorArgs(py::tuple& args, py::dict& kw) WOO_CXX11_OVERRIDE {if(py::len(kw)) Master().instance().checkApi(10102,"Constructing "+getClassName()+" with keywords will have no effect unless passed to GlSetup/S.gl.",/*pyWarn*/true); } \
	virtual void setFunctors_getRanges(const vector<shared_ptr<Object>>& ff, vector<shared_ptr<ScalarRange>>& rr){} \
	WOO_CLASS_BASE_DOC_ATTRS_PY(Klass,Functor,"Abstract functor for rendering :obj:`" #renderedType "` objects.",/*attrs*/,/*py*/ ; woo::converters_cxxVector_pyList_2way<shared_ptr<Klass>>();); \
	}; WOO_REGISTER_OBJECT(Klass); 
#define GL_DISPATCHER(Klass,Functor) class Klass: public Dispatcher1D<Functor>{public:\
	virtual void setFunctors_getRanges(const vector<shared_ptr<Object>>& ff, vector<shared_ptr<ScalarRange>>& rr){ for(const auto& f: ff) if(f && f->isA<Functor>()){ this->add(static_pointer_cast<Functor>(f)); f->cast<Functor>().setFunctors_getRanges(ff,rr); }} \
	WOO_DISPATCHER1D_FUNCTOR_DOC_ATTRS_CTOR_PY(Klass,Functor,/* doc generated by macro */,/*attrs*/,/*ctor*/,/*py*/); \
	}; WOO_REGISTER_OBJECT(Klass);

#include<woo/pkg/dem/Particle.hpp>
#include<woo/pkg/dem/Contact.hpp>


GL_FUNCTOR(GlNodeFunctor,TYPELIST_2(const shared_ptr<Node>&, const GLViewInfo&),Node);
GL_DISPATCHER(GlNodeDispatcher,GlNodeFunctor);

GL_FUNCTOR(GlFieldFunctor,TYPELIST_2(const shared_ptr<Field>&, GLViewInfo*),Field);
GL_DISPATCHER(GlFieldDispatcher,GlFieldFunctor);

#endif /* WOO_OPENGL */
